package com.sendi.sql;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Vector;

public class JavaDataBase {

	private DatabaseTool dbt = new DatabaseTool();
	
	/**
	 * execute the sql progress
	 * @param sql
	 * @return Vector<Vector<String>> result
	 */
	public Vector<Vector<String>> execute(String sql){
		Vector<Vector<String>> result = new Vector<Vector<String>>();
		String[] keyword = sql.split(" ");
		if (keyword.length<3) {
			System.out.println("sql语法错误："+sql);
			System.exit(-1);
		}else if(keyword[0].equals("create")){
			String tableName = keyword[1];
			dbt.createTable(tableName, getKeyWord(keyword[2]));
		}else if(keyword[0].equals("insert")){
			String tableName = keyword[1];
			dbt.insertTable(tableName, getKeyWord(keyword[2]));
		}else if(keyword[0].equals("update")){
			String tableName = keyword[1];
			Vector<String> headLineOrder = vecHeadOrder(tableName, keyword[4]);
			Vector<String> setLineOrder = vecHeadOrder(tableName, keyword[2]);
			Vector<Integer> updateLineNum = dbt.getLineNum(tableName, headLineOrder); 
			dbt.updateTable(tableName, setLineOrder, updateLineNum);
		}else if(keyword[0].equals("select")){
			Vector<String> vecHead;
			Vector<String> vecCondition;
			String tableName = keyword[3];		
			vecHead = selectUseVec(tableName, keyword[1]);
			if (keyword.length==4) {
				vecCondition= new Vector<String>();
				for (int i = 0; i < dbt.getTableHead(tableName).size(); i++) {
					vecCondition.add("null");
				}
			}else {
				vecCondition = selectUseVec(tableName, keyword[5]);
			}
			result = dbt.selectTableContent(tableName, vecHead, vecCondition);
		}else if(keyword[0].equals("delete")){
			String tableName = keyword[2];
			Vector<String> vecCondition;
			vecCondition = vecHeadOrder(tableName, keyword[4]);
			Vector<Integer> deleteLineNum = dbt.getLineNum(tableName, vecCondition);
			if (deleteLineNum.size()!=0) {
				dbt.deleteTableLine(tableName, deleteLineNum);				
			}else {
				System.out.println("没有合适删除条件的对象："+sql);
			}
		}else {
			System.out.println("无法判断sql语句："+sql);
			System.exit(-1);
		}
		return result;
	}
	
	/**
	 * get the select use key
	 * @param tableName
	 * @param selectKey
	 * @return
	 */
	private Vector<String> selectUseVec(String tableName,String selectKey) {
		// TODO Auto-generated method stub
		Vector<String> output = new Vector<String>();
		
		if (selectKey.equals("*")) {
			output = dbt.getTableHead(tableName);
		}else {
			output = vecHeadOrder(tableName, selectKey);
		}
		
		return output;
	}
	
	/**
	 * get the line order of the database with the condition
	 * @param tableName
	 * @param conditionWord (age=126,id=99)
	 * @return
	 */
	private Vector<String> vecHeadOrder(String tableName,String conditionWord) {
		// TODO Auto-generated method stub
		Vector<String> conditionKey = getKeyWord(conditionWord);
		Vector<String> tableHead = dbt.getTableHead(tableName);
		Vector<String> headOrderKey = new Vector<String>();
		
		for (int i = 0; i < tableHead.size(); i++) {
			String strAdd = "null";
			for (int j = 0; j < conditionKey.size(); j++) {
				String strTemp = conditionKey.elementAt(j);
				if (strTemp.contains("=")) {
					String[] strSplit = strTemp.split("=");
					if (strSplit[0].equals(tableHead.elementAt(i))) {
						strAdd = transForWord(strSplit[1]);
					}
				}else {
					if (strTemp.equals(tableHead.elementAt(i))) {
						strAdd = strTemp;
					}
				}
			}
			headOrderKey.add(strAdd);
		}
		
		int adoptDEC = 0;
		for (int i = 0; i < headOrderKey.size(); i++) {
			if (!headOrderKey.elementAt(i).equals("null")) {
				adoptDEC++;
			}
		}

		if (adoptDEC!=conditionKey.size()) {
			System.out.println("属性匹配出错，可能是单词拼写错误："+conditionWord);
			System.exit(-1);
		}
		
		return headOrderKey;
	}
	
	/**
	 * get key word for sql as the flash (id,name,age=13)
	 * @param keyword
	 */
	private Vector<String> getKeyWord(String keyword) {
		// TODO Auto-generated method stub
		Vector<String> output = new Vector<String>();
		
		String strTemp = keyword.substring(1, keyword.length()-1);
		String[] key;
		if (strTemp.contains(",")) {
			key = strTemp.split(",");
		}else{
			key = new String[1];
			key[0] = strTemp;
		}
		
		for (int i = 0; i < key.length; i++)
			output.add(transForWord(key[i]));
		
		return output;
	}
	
	/**
	 * transfor word to other whichever you want to get
	 * @param input
	 * @return
	 */
	private String transForWord(String input) {
		// TODO Auto-generated method stub
		String output = "";
		if (input.equals("''")) {
			output = " ";
		}else {
			output = input;
		}
		
		return output;
	}
}


class DatabaseTool {

	FileRandW frw = new FileRandW();
	
	public DatabaseTool() {
		// TODO Auto-generated constructor stub
	}
	
	/**
	 * create database table
	 * @param tableName
	 */
	void createTable(String tableName) {
		// TODO Auto-generated method stub
		frw.createFile(tableName+".csv");
	}
	void createTable(String tableName,Vector<String> tableHead) {
		String strTemp = "";
		frw.createFile(tableName+".csv");
		if (tableHead.size()==0) {
			System.out.println("表头发生错误：DatabaseTool.createTable(String tableName,Vector<String> tableHead)");
			System.exit(-1);
		}
		for (int i = 0; i < tableHead.size(); i++) {
			if (i==0) {
				strTemp = tableHead.elementAt(0);
			}else {
				strTemp += (","+tableHead.elementAt(i));
			}
		}
		frw.pRINTLN(strTemp);
	}
	
	/**
	 * delete database table(未完成，待定)
	 * @param tableName
	 */
	void deleteTable(String tableName){
		
	}
	
	/**
	 * insert content to table
	 * @param tableName
	 * @param tableContent
	 */
	void insertTable(String tableName, Vector<String> tableContent){
		frw.selsectFile(tableName+".csv");
		frw.createFile(tableName+".csv");
		if(frw.getInformation(0)=="empty"){
			System.out.println("插入的数据无表头：DatabaseTool.insertTable(String tableName, Vector<String> tableContent)");
			frw.pRINTLN();
			System.exit(-1);
		}else {
			String strTemp = "";
			int headLength = frw.getInformation(0).split(",").length;
			if (headLength!= tableContent.size()) {
				System.out.println("插入数据与表头不符：DatabaseTool.insertTable(String tableName, Vector<String> tableContent)");
				frw.pRINTLN();
				System.exit(-1);
			}else {
				for (int i = 0; i < headLength; i++) {
					if (i==0) {
						strTemp = tableContent.elementAt(0);
					}else {
						strTemp += (","+tableContent.elementAt(i));
					}
				}
				frw.pRINTLN(strTemp);
			}
		}		
	}
	
	/**
	 * update the table content
	 * @param tableName
	 * @param tableContent
	 * @param updateLine
	 */
	void updateTable(String tableName, Vector<String> tableContent, Vector<Integer> updateLine) {
		// TODO Auto-generated method stub
		frw.selsectFile(tableName+".csv");
		frw.createFile(tableName+".csv");
		if(frw.getInformation(0)=="empty"){
			System.out.println("更新数据无表头：DatabaseTool.updateTable(String tableName, Vector<String> tableContent, int updateLine)");
			frw.pRINTLN();
			System.exit(-1);
		}else {
			Vector<String> vecUpdate = new Vector<String>();
			Vector<String> vecTemp = frw.getInformation(updateLine);
			for (int i = 0; i < vecTemp.size(); i++) {
				String strTemp = "";
				String[] strUpdateUse = vecTemp.elementAt(i).split(",");
				for (int j = 0; j < tableContent.size(); j++) {
					if (tableContent.elementAt(j).equals("null")) {
						strTemp += strUpdateUse[j]+",";
					}else {
						strTemp += tableContent.elementAt(j)+",";
					}
				}
				strTemp = strTemp.substring(0, strTemp.length()-1);
				vecUpdate.add(strTemp);
			}
			frw.pRINTLN(vecUpdate, updateLine);
		}
	}
	
	/**
	 * delete some of the table content
	 * @param tableName
	 * @param deleteLine
	 */
	void deleteTableLine(String tableName,Vector<Integer> deleteLineNum){
		frw.selsectFile(tableName+".csv");
		frw.createFile(tableName+".csv");
		frw.dELETE(deleteLineNum);
	}
	
	/**
	 * select some of the table content
	 * @param tableName
	 * @param vecHead
	 * @param vecCondition
	 * @return 
	 */
	Vector<Vector<String>> selectTableContent(String tableName,Vector<String> vecHead,Vector<String> vecCondition) {
		// TODO Auto-generated method stub
		Vector<Vector<String>> output = new Vector<Vector<String>>();
		frw.selsectFile(tableName+".csv");
		Vector<Integer> lineNum = getLineNum(tableName, vecCondition);
		for (int i = 0; i < lineNum.size(); i++) {
			String strTemp = frw.getInformation(lineNum.elementAt(i));
			String[] strSav =  strTemp.split(",");
			Vector<String> vecTemp = new Vector<String>();
			for (int j = 0; j < strSav.length; j++) {
				if (!vecHead.elementAt(j).equals("null")) {
					vecTemp.add(strSav[j]);				
				}
			}
			output.add(vecTemp);
		}
		return output;
	}
	
	/**
	 * get the line number with the condition of the table
	 * @param tableName
	 * @param condition
	 * @return
	 */
	Vector<Integer> getLineNum(String tableName,Vector<String> condition) {
		// TODO Auto-generated method stub
		Vector<Integer> output = new Vector<Integer>();
		frw.selsectFile(tableName+".csv");
		
		for (int i = 1; i < frw.getInforLength(); i++) {
			String strTemp = frw.getInformation(i);
			String[] tableContent;
			if (strTemp.contains(",")) {
				tableContent = strTemp.split(",");
			}else {
				tableContent = new String[1];
				tableContent[0] = strTemp;
			}
			
			boolean addDEC = true;
			for (int j = 0; j < tableContent.length; j++) {
				if (condition.elementAt(j).equals("null")) {					
				}else if(condition.elementAt(j).equals(tableContent[j])){
				}else {
					addDEC = false;
				}
			}
			if (addDEC) {
				output.add(i);
			}
		}
		
		return output;
	}
	
	/**
	 * get the head of the table
	 * @param tableName
	 * @return
	 */
	Vector<String> getTableHead(String tableName) {
		// TODO Auto-generated method stub
		Vector<String> output = new Vector<String>();
		frw.selsectFile(tableName+".csv");
		String strTemp = frw.getInformation(0);
		String[] strTitle = strTemp.split(",");
		for (int i = 0; i < strTitle.length; i++) 
			output.add(strTitle[i]);
		
		return output;
	}
	
	/**
	 * change the vector construct
	 * @param vecChange
	 */
	void changeVecConstruct(Vector<Vector<String>> vecChange){
		Vector<Vector<String>> vecSave = new Vector<Vector<String>>();
		for (int i = 0; i < vecChange.elementAt(0).size(); i++) {
			Vector<String> vecTemp =new Vector<String>();
			for (int j = 0; j < vecChange.size(); j++) {
				vecTemp.add(vecChange.elementAt(j).elementAt(i));
			}
			vecSave.add(vecTemp);
		}
		vecChange.clear();
		for (int i = 0; i < vecSave.size(); i++) {
			vecChange.add(vecSave.elementAt(i));
		}
	}
}

class FileRandW {
	
	private FileWriter file;// write file use
	private PrintWriter out_to_file;// write file use
	private BufferedReader srcFile;// read file use
	private Vector<String> vecTemp = new Vector<String>();//save the data of database

	public FileRandW() {
		// TODO Auto-generated constructor stub
	}
	
	/**
	 * create file with the file name of string(fileName)
	 * @param fileName
	 */
	void createFile(String fileName) {
		// TODO Auto-generated method stub
		try {
			//start to create file and preper to write and read
			file = new FileWriter(fileName);
			out_to_file = new PrintWriter(file);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
	/**
	 * select file with the file name of string(fileName)
	 * @param fileName
	 */
	void selsectFile(String fileName) {
		// TODO Auto-generated method stub
		try {
			srcFile = new BufferedReader(new InputStreamReader(
					new FileInputStream(fileName)));
			String strLine;
			vecTemp.clear();
			while ((strLine = srcFile.readLine()) != null) {
				vecTemp.add(strLine);
			}
			srcFile.close();
//			createFile(fileName);	
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	/**
	 * delete file with the file name of string(fileName)
	 * @param fileName
	 * 此方法有问题，待改正
	 */
	void deleteFile(String fileName) {
		// TODO Auto-generated method stub
		try {
			//start to create file and preper to write and read
			File deleteFile = new File(fileName);
			file.close();
			deleteFile.delete();
		} catch (Exception e) {
			// TODO: handle exception
			File deleteFile = new File(fileName);
			deleteFile.delete();
		}
	}
	
	/**
	 * flush the vector data to the file
	 */
	private void vecFLUSHfile() {
		// TODO Auto-generated method stub
		try {
			if (vecTemp.size()!=0) {
				for (int i = 0; i < vecTemp.size(); i++) {
					out_to_file.println(vecTemp.elementAt(i));
				}
				out_to_file.flush();
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
	/**
	 * add information to file
	 * @param input
	 */
	void pRINTLN(){//刷新
		vecFLUSHfile();
	}
	void pRINTLN(String input) {//插入
		// TODO Auto-generated method stub
		try {
			vecFLUSHfile();
			out_to_file.println(input);
			out_to_file.flush();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	void pRINTLN(Vector<String> input,Vector<Integer> setNum) {//批量更新
		if (input.size()!=setNum.size()) {
			System.out.println("批量更新数据长度发生异常");
			pRINTLN();
			System.exit(-1);
		}else {
			try {
				for (int i = 0; i < setNum.size(); i++) {
					vecTemp.set(setNum.elementAt(i), input.elementAt(i));
				}
				pRINTLN();
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * delete information from file
	 * @param deleteLineNum
	 */
	void dELETE(Vector<Integer> deleteLineNum) {
		// TODO Auto-generated method stub
		try {
			boolean decFlag = true;
			int numCount = 0;
			for (int i = 0; i < vecTemp.size(); i++) {
				if (decFlag) {
					if (i == deleteLineNum.elementAt(numCount)){
						numCount++;
						if (numCount==deleteLineNum.size()) {
							decFlag = false;
						}
						continue;
					}
				}
				out_to_file.println(vecTemp.elementAt(i));
			}	
			out_to_file.flush();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
	/**
	 * get information of the databases 
	 * @param setNum
	 * @return
	 */
	String getInformation(int setNum){
		if (vecTemp.size()==0) {
			return "empty";
		}else if(vecTemp.size()<setNum) {
			return "error";
		}else{
			return vecTemp.elementAt(setNum);
		}
	}
	
	Vector<String> getInformation(Vector<Integer> setNum){
		Vector<String> output = new Vector<String>();
		for (int i = 0; i < setNum.size(); i++) {
			String strTemp = getInformation(setNum.elementAt(i));
			output.add(strTemp);
		}
		return output;
	}
	
	/**
	 * get the length of the database vector
	 * @return
	 */
	int getInforLength(){
		return vecTemp.size();
	}
}
